package pool;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

/**
 * 为每个线程分配一个indexDoc缓存
 *
 * @Author: ycy
 * @CreateDate: 2020/5/28 13:55
 */
public class IndexDocThreadLocal {

  static Logger logger = LoggerFactory.getLogger(IndexDocThreadLocal.class);

  private static final ThreadLocal<IndexDocsCache> indexDocThreadLocal = new ThreadLocal();

  public static void init() {
    if (indexDocThreadLocal.get() == null) {
      indexDocThreadLocal.set(new IndexDocsCache());
      logger.info("IndexDocsCache init ok");
    }
  }

  public static IndexDoc getIndex() {
    return indexDocThreadLocal.get().get();
  }

  public static int getIndexCacheSize() {
    return indexDocThreadLocal.get().indexDocs.length;
  }

  public static void resizeIndex() {
    indexDocThreadLocal.get().resize();
  }

  static class IndexDocsCache {
    private IndexDoc[] indexDocs = null;

    //被使用的indexDocs的指针偏移量
    private volatile int hand = 0;

    //初始化
    private IndexDocsCache() {
      int length = 30;
      initIndexDocs(length);
    }

    private void initIndexDocs(int length) {
      this.indexDocs = new IndexDoc[length];
      for (int i = 0; i < length - 1; i++) {
        this.indexDocs[i] = IndexDoc.newIndexDocForCache();
      }
    }

    //线程安全
    private IndexDoc get() {
      synchronized (this) {
        grow();
        IndexDoc indexDoc = indexDocs[hand];
        if (indexDoc == null) {
          indexDocs[hand] = IndexDoc.newIndexDocForCache();
          indexDoc = indexDocs[hand];
        }
        hand++;
        return indexDoc;
      }
    }

    private void grow() {
      int oldCapacity = indexDocs.length;
      if (hand >= oldCapacity) {
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //数组扩容
        this.indexDocs = Arrays.copyOf(this.indexDocs, newCapacity);
        if (this.indexDocs.length > 1000000)
          logger.warn("resize ok. grow length {} ,now hand {}, but it too large!!!", this.indexDocs.length, hand);
      }
    }

    //线程安全
    private void resize() {
      synchronized (this) {
        for (int i = 0; i < hand + 1; i++) {
          try {
            invalid(this.indexDocs[i]);
          } catch (Exception e) {
            this.indexDocs[i] = IndexDoc.newIndexDocForCache();
            e.printStackTrace();
          }
        }
        hand = 0;
      }
    }

    private void invalid(IndexDoc indexDoc) {
      //初始化基本值
      if (indexDoc != null) {
        indexDoc.clear();
      }
    }
  }

  public static void main(String[] args) {
    char c = 0;
    System.out.println(c);
  }

}
